# -*- coding: utf-8 -*-

from rest_framework.decorators import action
from core.response import JsonResponse
from core.viewset import CustomModelViewSet
from django.http import FileResponse
from apps.tms.models import Job, JobExecution, JobLog
from apps.tms.job.serializers import *
from apps.tms.job.filters import *
from apps.tms.job.utils.results import *
from apps.tms.job.resources import *
from apps.tms import tasks
from pathlib import Path
from application.settings import BASE_DIR


class JobViewSet(CustomModelViewSet):
    """
    测试执行管理接口
    list:查询
    create:新增
    update:修改
    retrieve:单例
    destroy:删除
    """

    queryset = Job.objects.all()
    serializer_class = JobSerializer
    filterset_class = JobFilterSet
    list_serializer_class = JobListSerializer

    @action(detail=False, methods=["PUT"])
    def start(self, request, *args, **kwargs):
        """
        开始执行任务
        """
        try:
            for data in request.data:
                tasks.start(data)
            return JsonResponse(msg="执行成功")
        except Exception as ex:
            return JsonResponse(code=500, msg=f"执行失败：{str(ex)}")

    @action(detail=True, methods=["PUT"])
    def retry(self, request, *args, **kwargs):
        """
        开始重试任务
        """
        try:
            tasks.retry(
                kwargs.get("pk"),
                request.data.get("job_execution"),
                request.data.get("testcases"),
                request.data.get("sync_case"),
                request.data.get("executor"),
            )
            return JsonResponse(msg="重试成功")
        except Exception as ex:
            return JsonResponse(code=500, msg=f"重试失败：{str(ex)}")

    @action(detail=False, methods=["PUT"])
    def stop(self, request, *args, **kwargs):
        """
        停止执行任务
        """
        try:
            for data in request.data:
                tasks.stop(data)
            return JsonResponse(msg="停止成功")
        except Exception as ex:
            return JsonResponse(code=500, msg=f"停止失败：{str(ex)}")

    @action(detail=False, methods=["PUT"])
    def stop_no_wait(self, request, *args, **kwargs):
        """
        停止执行任务
        """
        try:
            for data in request.data:
                tasks.stop_no_wait(data)
            return JsonResponse(msg="停止成功")
        except Exception as ex:
            return JsonResponse(code=500, msg=f"停止失败：{str(ex)}")


class JobExecutionViewSet(CustomModelViewSet):
    """
    任务执行记录管理接口
    list:查询
    create:新增
    update:修改
    retrieve:单例
    destroy:删除
    """

    queryset = JobExecution.objects.all()
    serializer_class = JobExecutionSerializer
    filterset_class = JobExecutionFilterSet

    @action(detail=True, methods=["GET"])
    def result(self, request, *args, **kwargs):
        try:
            data = {"number": [], "pass": [], "fail": [], "block": [], "norun": []}

            step_analysis_todo = 0
            step_analysis_env = 0
            step_analysis_case = 0
            step_analysis_script = 0
            step_analysis_bug = 0
            testcases = JobLog.objects.filter(job_execution=kwargs.get("pk"))
            for testcase in testcases:
                step_block = 0
                step_fail = 0
                step_pass = 0
                step_norun = 0
                for step in testcase.steps:
                    result = step.get("result")
                    analysis = step.get("analysis")
                    step_block = (
                        step_block + 1 if (result == Result.BLOCK.value) else step_block
                    )
                    step_fail = (
                        step_fail + 1 if (result == Result.FAIL.value) else step_fail
                    )
                    step_pass = (
                        step_pass + 1 if (result == Result.PASS.value) else step_pass
                    )
                    step_norun = step_norun if (result) else step_norun + 1
                    step_analysis_todo = (
                        step_analysis_todo + 1
                        if (analysis == Analysis.TODO.value)
                        else step_analysis_todo
                    )
                    step_analysis_env = (
                        step_analysis_env + 1
                        if (analysis == Analysis.ENV.value)
                        else step_analysis_env
                    )
                    step_analysis_case = (
                        step_analysis_case + 1
                        if (analysis == Analysis.CASE.value)
                        else step_analysis_case
                    )
                    step_analysis_script = (
                        step_analysis_script + 1
                        if (analysis == Analysis.SCRIPT.value)
                        else step_analysis_script
                    )
                    step_analysis_bug = (
                        step_analysis_bug + 1
                        if (analysis == Analysis.BUG.value)
                        else step_analysis_bug
                    )
                data["number"].append(testcase.number)
                data["block"].append(step_block)
                data["fail"].append(step_fail)
                data["pass"].append(step_pass)
                data["norun"].append(step_norun)

            cases = {}
            cases["norun"] = (
                JobLog.objects.filter(job_execution=kwargs.get("pk"))
                .filter(status="0")
                .count()
            )
            cases["running"] = (
                JobLog.objects.filter(job_execution=kwargs.get("pk"))
                .filter(status="2")
                .count()
            )
            cases["pass"] = (
                JobLog.objects.filter(job_execution=kwargs.get("pk"))
                .filter(status="3")
                .count()
            )
            cases["fail"] = (
                JobLog.objects.filter(job_execution=kwargs.get("pk"))
                .filter(status="4")
                .count()
            )
            cases["block"] = (
                JobLog.objects.filter(job_execution=kwargs.get("pk"))
                .filter(status="5")
                .count()
            )
            cases_total = (
                cases["norun"] + cases["pass"] + cases["fail"] + cases["block"]
            )
            cases_passrate = (
                100
                if (cases_total == 0)
                else "%.2f" % (cases["pass"] / cases_total * 100)
            )
            cases["summary"] = (
                f"共计：{cases_total} 个用例，执行通过率：{cases_passrate} %"
            )
            data["cases"] = cases

            steps = {}
            steps["norun"] = sum(data["norun"])
            steps["pass"] = sum(data["pass"])
            steps["fail"] = sum(data["fail"])
            steps["block"] = sum(data["block"])
            steps_total = sum(
                [steps["norun"], steps["pass"], steps["fail"], steps["block"]]
            )
            steps_passrate = (
                100
                if (steps_total == 0)
                else "%.2f" % (steps["pass"] / steps_total * 100)
            )
            steps["summary"] = (
                f"共计：{steps_total} 个步骤，执行通过率：{steps_passrate} %"
            )
            data["steps"] = steps

            case_analysis = {}
            case_analysis["todo"] = (
                JobLog.objects.filter(job_execution=kwargs.get("pk"))
                .filter(analysis="0")
                .count()
            )
            case_analysis["env"] = (
                JobLog.objects.filter(job_execution=kwargs.get("pk"))
                .filter(analysis="1")
                .count()
            )
            case_analysis["case"] = (
                JobLog.objects.filter(job_execution=kwargs.get("pk"))
                .filter(analysis="2")
                .count()
            )
            case_analysis["script"] = (
                JobLog.objects.filter(job_execution=kwargs.get("pk"))
                .filter(analysis="3")
                .count()
            )
            case_analysis["bug"] = (
                JobLog.objects.filter(job_execution=kwargs.get("pk"))
                .filter(analysis="4")
                .count()
            )
            case_analysis_total = sum(
                [
                    case_analysis["todo"],
                    case_analysis["env"],
                    case_analysis["case"],
                    case_analysis["script"],
                    case_analysis["bug"],
                ]
            )
            case_analysis_rate = (
                100
                if (case_analysis_total == 0)
                else "%.2f"
                % (
                    (case_analysis_total - case_analysis["todo"])
                    / case_analysis_total
                    * 100
                )
            )
            case_analysis["summary"] = (
                f"共计：{case_analysis_total} 个异常，分析完成率：{case_analysis_rate} %"
            )
            data["case_analysis"] = case_analysis

            step_analysis = {}
            step_analysis["todo"] = step_analysis_todo
            step_analysis["env"] = step_analysis_env
            step_analysis["case"] = step_analysis_case
            step_analysis["script"] = step_analysis_script
            step_analysis["bug"] = step_analysis_bug
            step_analysis_total = sum(
                [
                    step_analysis["todo"],
                    step_analysis["env"],
                    step_analysis["case"],
                    step_analysis["script"],
                    step_analysis["bug"],
                ]
            )
            step_analysis_rate = (
                100
                if (step_analysis_total == 0)
                else "%.2f"
                % (
                    (step_analysis_total - step_analysis["todo"])
                    / step_analysis_total
                    * 100
                )
            )
            step_analysis["summary"] = (
                f"共计：{step_analysis_total} 个异常，分析完成率：{step_analysis_rate} %"
            )
            data["step_analysis"] = step_analysis

            return JsonResponse(data=data, msg="获取统计信息成功")
        except Exception as e:
            return JsonResponse(code=500, msg=f"获取统计信息失败：{str(e)}")


class JobLogViewSet(CustomModelViewSet):
    """
    任务日志接口
    list:查询
    create:新增
    update:修改
    retrieve:单例
    destroy:删除
    """

    queryset = JobLog.objects.all()
    serializer_class = JobLogSerializer
    list_serializer_class = JobLogListSerializer
    create_serializer_class = JobLogCreateUpdateSerializer
    update_serializer_class = JobLogCreateUpdateSerializer
    filterset_class = JobLogFilterSet
    export_resources = JobLogResources


class JobPluginViewSet(CustomModelViewSet):
    """
    任务插件接口
    list:查询
    create:新增
    update:修改
    retrieve:单例
    destroy:删除
    """

    queryset = JobPlugin.objects.all()
    serializer_class = JobPluginSerializer
    permission_classes = []

    @action(detail=False, methods=["POST"])
    def download(self, request, pk=None, *args, **kwargs):
        file_name = request.data.get("file")
        file_path = BASE_DIR.joinpath(Path(file_name).relative_to("/"))
        response = FileResponse(open(file_path, "rb"))
        return response
